package gui;

import events.CustomEvent;
import events.listener.CanvasListener;
import gui.addons.Processbar;

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.image.BufferStrategy;
import java.util.ArrayList;
import java.util.HashMap;

import sprites.CharacteristicSprite;
import sprites.Pacman;
import sprites.Sprite;
import sprites.characteristic.MonsterSpawn;
import sprites.characteristic.PlayerSpawn;

import main.EventManager;
import main.ImageLoader;

public class GameCanvas extends Canvas implements Runnable, CanvasListener {

	private final int HEIGHT = 600;
	private final int WIDTH = 800;
	private final int DEF_TILE = 40;

	private boolean ready = false;
	private BufferStrategy buffer;
	private Graphics graphics;

	private Thread thread = null;
	private Processbar pBar = null;
	private Pacman pacman = null;

	private HashMap<Point, Sprite> map = null;
	private ArrayList<PlayerSpawn> playerSpawn;
	private ArrayList<MonsterSpawn> monsterSpawn;
	
	private int mapheight;
	private int mapwidth;

	public GameCanvas() {
		EventManager.addListener(this);
		setup();
	}

	@Override
	public void run() {

		while (true) {
			try {
				if (this.isVisible()) {
					render();
					draw();
				}
				Thread.sleep(1);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	public void addNotify() {
		super.addNotify();

		// Creating buffered strategy.
		createBufferStrategy(2);
		buffer = getBufferStrategy();
		requestFocus();
		start();
	}

	private void start() {
		if (thread == null) {
			thread = new Thread(this, "Pacman canvas");
			thread.start();
		}
	}

	private void render() {
		graphics = buffer.getDrawGraphics();

		// Clearing old data
		graphics.setColor(Color.black);
		graphics.fillRect(0, 0, WIDTH, HEIGHT);

		if (graphics instanceof Graphics2D) {
			((Graphics2D) graphics).setRenderingHint(
					RenderingHints.KEY_ANTIALIASING,
					RenderingHints.VALUE_ANTIALIAS_ON);

		}

		if (!ready) {
			drawWaiting(graphics);
		} else {
			drawMap(graphics);
			drawPac(graphics);
		}

	}

	private void drawPac(Graphics g) {
		if (pacman == null) {
			pacman = new Pacman("Nimi siia");
		}
		if (!pacman.isActive()) {
			pacman.setSpawns(playerSpawn);
			pacman.setMap(map);
			pacman.setActive(true);
		}
		pacman.draw(g);
	}
	private void drawMap(Graphics g) {
		for (int y = 0; y < map.size(); y++) {
			for (int x = 0; x < mapwidth; x++) {
				Sprite sp = map.get(new Point(x, y));
				if (sp != null) {
					sp.setX(x * DEF_TILE);
					sp.setY(y * DEF_TILE);
					sp.draw(g);
				}
			}
		}
	}

	private void setup() {
		this.setIgnoreRepaint(true);
		this.setVisible(true);
		this.setSize(WIDTH, HEIGHT);
	}

	private void drawWaiting(Graphics g) {
		if (!ImageLoader.isReady()) {
			if (pBar == null) {
				pBar = new Processbar(ImageLoader.getTotal(), HEIGHT, WIDTH);
			}
			pBar.draw(g, ImageLoader.getCurrent());
		} else {
			ready = true;
		}
	}

	private void draw() {
		if (!buffer.contentsLost()) {
			buffer.show();
		}
		if (graphics != null) {
			graphics.dispose();
		}
	}

	public void addMap(HashMap<Point, Sprite> mp, int height, int width, ArrayList<MonsterSpawn> monsterSpawn, ArrayList<PlayerSpawn> playerSpawn) {
		mapheight = height;
		mapwidth = width;
		map = mp;
		this.monsterSpawn = monsterSpawn;
		this.playerSpawn = playerSpawn;

		ready = true;
	}

	@Override
	public void EventOccurred(CustomEvent evt) {
		evt.run(this);
	}
}
